#ifndef _GRO_BACKEND_OPENGL_H__
#define _GRO_BACKEND_OPENGL_H__

/*
GRO_GUI backend: OpenGL

GRO_LineH
GRO_LineHBlend
GRO_LineV
GRO_LineVBlend
GRO_Line
GRO_LineBlend

GRO_Rect
GRO_RectBlend
GRO_RectFilled
GRO_RectFilledBlend
GRO_Circle
GRO_CircleBlend
GRO_CircleFilled
GRO_CircleFilledBlend
//GRO_Ellipse
//GRO_EllipseBlend
GRO_EllipseFilled
GRO_EllipseFilledBlend

GRO_TrigonFade
GRO_SetClip
GRO_DirtyAdd
GRO_RectIntersect

*/


#include <GL/gl.h>
#include <cmath>

namespace GRO
{
        
    class Renderer_OpenGL : public Renderer
    {
        public:
        
        SDL_Rect currentClip;
        
        Renderer_OpenGL()
            : Renderer()
        {}
        Renderer_OpenGL(SDL_PixelFormat* format)
            : Renderer(format)
        {}
        
        virtual void Blit(Gui* gui, SDL_Surface* image, SDL_Rect* s, SDL_Rect* d)
        {
            if(gui != NULL)
                ;//SDL_BlitSurface(image, s, gui->screen, d);
        }
        
        virtual void Pixel(Gui* gui, Sint16 x, Sint16 y, Uint32 color)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_POINTS);
                glVertex3f(x, y, 1.0f);
                glEnd();
            }
        }

        virtual void LineH(Gui* gui, Sint16 x1, Sint16 y, Sint16 x2, Uint32 color)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_LINES);
                glVertex3f(x1, y, 1.0f);
                glVertex3f(x2, y, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x1, y, 1.0f);
                glVertex3f(x2, y, 1.0f);
                glEnd();
            }
        }

        virtual void LineHBlend(Gui* gui, Sint16 x1, Sint16 y, Sint16 x2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b, alpha);
                glBegin(GL_LINES);
                glVertex3f(x1, y, 1.0f);
                glVertex3f(x2, y, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x1, y, 1.0f);
                glVertex3f(x2, y, 1.0f);
                glEnd();
            }
        }

        virtual void LineV(Gui* gui, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_LINES);
                glVertex3f(x, y1, 1.0f);
                glVertex3f(x, y2, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x, y1, 1.0f);
                glVertex3f(x, y2, 1.0f);
                glEnd();
            }
        }

        virtual void LineVBlend(Gui* gui, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b, alpha);
                glBegin(GL_LINES);
                glVertex3f(x, y1, 1.0f);
                glVertex3f(x, y2, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x, y1, 1.0f);
                glVertex3f(x, y2, 1.0f);
                glEnd();
            }
        }

        virtual void Line(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_LINES);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
            }
        }

        virtual void LineBlend(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b, alpha);
                glBegin(GL_LINES);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
            }
        }

        virtual void LineBlendAA(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b, alpha);
                glBegin(GL_LINES);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
                glBegin(GL_POINTS);
                glVertex3f(x1, y1, 1.0f);
                glVertex3f(x2, y2, 1.0f);
                glEnd();
            }
        }




        virtual void Rect(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
        {
            if(gui != NULL)
            {
                /*Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_LINE_LOOP);			// Draw A Quad
                glVertex3f(x1, y1, 1.0f);		// Top Left
                glVertex3f(x2, y1, 1.0f);		// Top Right
                glVertex3f(x2, y2, 1.0f);		// Bottom Right
                glVertex3f(x1, y2, 1.0f);		// Bottom Left
                glEnd();*/
                LineH(gui, x1, y1, x2, color);
                LineH(gui, x1, y2, x2, color);
                LineV(gui, x1, y1, y2, color);
                LineV(gui, x2, y1, y2, color);
            }
        }

        virtual void RectBlend(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b, alpha);
                glBegin(GL_LINE_LOOP);			// Draw A Quad
                glVertex3f(x1, y1, 1.0f);		// Top Left
                glVertex3f(x2, y1, 1.0f);		// Top Right
                glVertex3f(x2, y2, 1.0f);		// Bottom Right
                glVertex3f(x1, y2, 1.0f);		// Bottom Left
                glEnd();
            }
        }

        virtual void RectFilled(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glBegin(GL_QUADS);			// Draw A Quad
                glVertex3f(x1, y1, 1.0f);		// Top Left
                glVertex3f(x2, y1, 1.0f);		// Top Right
                glVertex3f(x2, y2, 1.0f);		// Bottom Right
                glVertex3f(x1, y2, 1.0f);		// Bottom Left
                glEnd();
            }
        }

        virtual void RectFilledBlend(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                Uint8 r, g, b;
                SDL_GetRGB(color, &format, &r, &g, &b);
                glColor4ub(r,g,b,alpha);
                glBegin(GL_QUADS);			// Draw A Quad
                glVertex3f(x1, y1, 1.0f);		// Top Left
                glVertex3f(x2, y1, 1.0f);		// Top Right
                glVertex3f(x2, y2, 1.0f);		// Bottom Right
                glVertex3f(x1, y2, 1.0f);		// Bottom Left
                glEnd();
            }
        }


                
        // Colors in CCW order
        virtual void RectFade(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 c1, Uint32 c2, Uint32 c3, Uint32 c4)
        {
            if(gui != NULL)
            {
                glShadeModel(GL_SMOOTH);
                Uint8 r, g, b;
                glBegin(GL_QUADS);
                SDL_GetRGB(c1, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glVertex3f(x1, y1, 1.0f);		// Top Left
                SDL_GetRGB(c2, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glVertex3f(x1, y2, 1.0f);		// Bottom Left
                SDL_GetRGB(c3, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glVertex3f(x2, y2, 1.0f);		// Bottom Right
                SDL_GetRGB(c4, &format, &r, &g, &b);
                glColor3ub(r,g,b);
                glVertex3f(x2, y1, 1.0f);		// Top Right
                glEnd();
                ;//SPG_Point points[] = {{x1,y1}, {x1,y2}, {x2,y2}, {x2,y1}};
                ;//Uint32 colors[] = {c1, c2, c3, c4};
                ;//SPG_PolygonFade(gui->screen, 4, points, colors);
            }
        }

        virtual void RectRound(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 radius, Uint32 color)
        {
            if(gui != NULL)
            {
                Sint16 minX = (x1 < x2? x1 : x2) + (Sint16)(radius);
                Sint16 maxX = (x1 > x2? x1 : x2) - (Sint16)(radius);
                Sint16 minY = (y1 < y2? y1 : y2) + (Sint16)(radius);
                Sint16 maxY = (y1 > y2? y1 : y2) - (Sint16)(radius);
                LineH(gui, minX,y1,maxX,color);
                LineH(gui, minX,y2,maxX,color);
                LineV(gui,x1,minY,maxY,color);
                LineV(gui,x2,minY,maxY,color);

                ArcBlend(gui, minX, minY, radius, 180, 270, color, SDL_ALPHA_OPAQUE);
                ArcBlend(gui, maxX, minY, radius, 270, 360, color, SDL_ALPHA_OPAQUE);
                ArcBlend(gui, maxX, maxY, radius, 0, 90, color, SDL_ALPHA_OPAQUE);
                ArcBlend(gui, minX, maxY, radius, 90, 180, color, SDL_ALPHA_OPAQUE);
            }
        }

        virtual void RectRoundFilledBlend(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 radius, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
                ;//SPG_RectRoundFilledBlend(gui->screen, x1, y1, x2, y2, radius, color, alpha);
        }

        virtual void ArcBlend(Gui* gui, Sint16 x, Sint16 y, Sint16 radius, float startAngle, float endAngle, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
            {
                float angle;  // use as swap then use later
                float originalSA = startAngle;

                if(startAngle > endAngle)
                {
                    float swapa = endAngle;
                    endAngle = startAngle;
                    startAngle = swapa;
                }
                if(startAngle == endAngle)
                    return;
                
                // Big angle
                if(endAngle - startAngle >= 360)
                {
                    CircleBlend(gui, x, y, radius, color, alpha);
                    return;
                }
                
                // Shift together
                while(startAngle < 0 && endAngle < 0)
                {
                    startAngle += 360;
                    endAngle += 360;
                }
                while(startAngle > 360 && endAngle > 360)
                {
                    startAngle -= 360;
                    endAngle -= 360;
                }
                
                // Check if the angle to be drawn crosses 0
                bool crossesZero = (startAngle < 0 && endAngle > 0) || (startAngle < 360 && endAngle > 360);
                
                // Push all values to 0 <= angle < 360
                while(startAngle >= 360)
                    startAngle -= 360;
                while(endAngle >= 360)
                    endAngle -= 360;
                while(startAngle < 0)
                    startAngle += 360;
                while(endAngle < 0)
                    endAngle += 360;
                
                if(endAngle == 0)
                    endAngle = 360;
                else if(crossesZero)
                {
                    ArcBlend(gui, x, y, radius, originalSA, 359, color, alpha);
                    startAngle = 0;
                }
                
                Sint16 dx = 0;
                Sint16 dy = (Sint16)(radius);
                Sint16 p = 1 - (Sint16)(radius);
                Sint16 d_e = 3;
                Sint16 d_se = -2 * (Sint16)(radius) + 5;
                
                do
                {
                    // Calculate the angle the current point makes with the circle center
                    angle = atan2((float)dy, (float)dx)*57.2957795f;
                    
                    // draw the circle points as long as they lie in the range specified
                    
                    if(dx)
                    {
                        // draw point in range 45 to 90 degrees
                        if (angle >= startAngle && angle <= endAngle) {
                            Pixel(gui, x + dx, y + dy, color);
                        }
                        // draw point in range 180 to 225 degrees
                        if (270 - angle >= startAngle && 270 - angle <= endAngle) {
                            Pixel(gui, x - dy, y - dx, color);
                        }
                        // draw point in range 225 to 270 degrees
                        if (angle + 180 >= startAngle && angle + 180 <= endAngle) {
                            Pixel(gui, x - dx, y - dy, color);
                        }
                        // draw point in range 315 to 360 degrees
                        if (angle + 270 >= startAngle && angle + 270 <= endAngle) {
                            Pixel(gui, x + dy, y - dx, color);
                        }
                    }
                    
                    // draw point in range 0 to 45 degrees
                    if (90 - angle >= startAngle && 90 - angle <= endAngle) {
                        Pixel(gui, x + dy, y + dx, color);
                    }

                    // draw point in range 90 to 135 degrees
                    if (180 - angle >= startAngle && 180 - angle <= endAngle) {
                        Pixel(gui, x - dx, y + dy, color);
                    }

                    // draw point in range 135 to 180 degrees
                    if (angle + 90 >= startAngle && angle + 90 <= endAngle) {
                        Pixel(gui, x - dy, y + dx, color);
                    }

                    // draw point in range 270 to 315 degrees
                    if (360 - angle >= startAngle && 360 - angle <= endAngle) {
                        Pixel(gui, x + dx, y - dy, color);
                    }


                    dx++;

                    if (p < 0)
                    {
                        p += d_e;
                        d_e += 2;
                        d_se += 2;
                    }
                    else
                    {
                        p += d_se;
                        d_e += 2;
                        d_se += 4;
                        dy--;
                    }
                }
                while (dx <= dy);
            }
        }
        
        void ArcFilledBlend()
        {
            /*
            Sint16 cx = 0;
            Sint16 cy = (Sint16)r;
            Sint16 df = 1 - cy;
            Sint16 d_e = 3;
            Sint16 d_se = -2*cy + 5;
            Sint16 xl, xr;
            
            if(startAngle > endAngle)
            {
                float swapa = endAngle;
                endAngle = startAngle;
                startAngle = swapa;
            }
            if(startAngle == endAngle)
                return;

            if(!spg_usedegrees)
            {
                startAngle *= DEGPERRAD;
                endAngle *= DEGPERRAD;
            }
            
            SPG_bool reflex = endAngle - startAngle > 180;
            
            Sint16 sx = (Sint16)(r*cos(startAngle*RADPERDEG));
            Sint16 sy = (Sint16)(r*sin(startAngle*RADPERDEG));
            Sint16 ex = (Sint16)(r*cos(endAngle*RADPERDEG));
            Sint16 ey = (Sint16)(r*sin(endAngle*RADPERDEG));
            
            float sm = sy/(float)(sx);
            float em = ey/(float)(ex);
            
            // Big angle
            if(endAngle - startAngle >= 360)
            {
                SPG_CircleFilledBlend(surf, x, y, r, color, alpha);
                return;
            }
            // coordinates overlap
            if(sy == ey && sx >= ex - 1 && ex + 1 <= sx && endAngle - startAngle > 350)
            {
                SPG_CircleFilledBlend(surf, x, y, r, color, alpha);
                return;
            }
            if(sy == ey && sx == ex && endAngle - startAngle < 10)
                return;
            
            
            // Push all values to 0 <= angle < 360
            while(startAngle >= 360)
                startAngle -= 360;
            while(endAngle >= 360)
                endAngle -= 360;
            while(startAngle < 0)
                startAngle += 360;
            while(endAngle < 0)
                endAngle += 360;
            
            // I should change these to sy and ey in case the angle rounds to 180
            SPG_bool bothTop = (startAngle > 180 && endAngle > 180);
            SPG_bool bothBot = (startAngle < 180 && endAngle < 180);
            //bool bothTop = sy < 0 && ey < 0;
            //bool bothBot = sy >= 0 && ey >= 0;
            
            // Use thse to fix special cases
            SPG_bool s180 = sy == 0 && sx < 0;
            SPG_bool s0 = sy == 0 && sx >= 0;
            SPG_bool e180 = ey == 0 && ex < 0;
            SPG_bool e0 = ey == 0 && ex >= 0;
            
            
            do
            {
                if(df >= 0)
                {
                    if(!bothTop)
                    {
                        // Draw bottom between lines
                        // Intercept of lines vs edge of circle
                        xl = ey > 0? (Sint16)max(cy/em + x, x - cx) : (Sint16)x - cx;
                        xr = sy > 0? (Sint16)min(cy/sm + x, x + cx) : (Sint16)x + cx;
                        if(xl <= xr && !(s180 && ey <= 0) && !(sy <= 0 && e0))
                            spg_linehblend(surf, xl, y + cy, xr, color, alpha);
                    }
                    else if(reflex)
                    {
                        // Draw entire bottom
                        spg_linehblend(surf, x - cx, y + cy, x + cx, color, alpha);
                        
                        // Draw separated top 
                        // sy <= 0, ey < 0, ex < sx
                        xl = x - cx;  // Intercept of lines vs edge of circle
                        xr = ey < 0? (Sint16)min(-cy/em + x, x + cx) : x + cx;
                        if(xl <= xr)
                            spg_linehblend(surf, xl, y - cy, xr, color, alpha);
                        
                        xl = sy < 0? (Sint16)max(-cy/sm + x, x - cx) : x - cx;
                        xr = x + cx;
                        if(xl <= xr)
                            spg_linehblend(surf, xl, y - cy, xr, color, alpha);
                            
                    }
                    if(!bothBot)
                    {
                        // Draw top between lines
                        xl = sy < 0? (Sint16)max(-cy/sm + x, x - cx) : (Sint16)x - cx;
                        xr = ey < 0? (Sint16)min(-cy/em + x, x + cx) : (Sint16)x + cx;
                        if(xl <= xr && !(e180 && sy >= 0))
                            spg_linehblend(surf, xl, y - cy, xr, color, alpha);
                    }
                    else if(reflex)
                    {
                        // Draw entire top
                        spg_linehblend(surf, x - cx, y - cy, x + cx, color, alpha);
                        
                        // Draw separated bottom
                        // sy >= 0, ey > 0, sx < ex
                        xl = x - cx;  // Intercept of lines vs edge of circle
                        xr = sy > 0? (Sint16)min(cy/sm + x, x + cx) : x + cx;
                        if(xl <= xr && !s0 && !(sy > 0 && e0))
                            spg_linehblend(surf, xl, y + cy, xr, color, alpha);
                        
                        xl = ey > 0? (Sint16)max(cy/em + x, x - cx) : x - cx;
                        xr = x + cx;
                        if(xl <= xr && !(sy > 0 && e0))
                            spg_linehblend(surf, xl, y + cy, xr, color, alpha);
                    }
                }
                if(cx != cy)
                {
                    if(!bothTop)
                    {
                        // Draw bottom between lines
                        xl = ey > 0? (Sint16)max(cx/em + x, x - cy) : (Sint16)x - cy;
                        xr = sy > 0? (Sint16)min(cx/sm + x, x + cy) : (Sint16)x + cy;
                        if(xl <= xr && !(s180 && ey <= 0) && !(sy <= 0 && e0))
                            spg_linehblend(surf, xl, y + cx, xr, color, alpha);
                    }
                    else if(reflex)
                    {
                        if(cx != 0)
                        {
                            // Draw entire bottom
                            spg_linehblend(surf, x - cy, y + cx, x + cy, color, alpha);
                        }
                        
                        // Draw separated top
                        // sy <= 0, ey < 0, ex < sx
                        xl = x - cy;  // Intercept of lines vs edge of circle
                        xr = ey < 0? (Sint16)min(-cx/em + x, x + cy) : x + cy;
                        if(xl <= xr)
                            spg_linehblend(surf, xl, y - cx, xr, color, alpha);
                        
                        xl = sy < 0? (Sint16)max(-cx/sm + x, x - cy) : x - cy;
                        xr = x + cy;
                        if(xl <= xr)
                            spg_linehblend(surf, xl, y - cx, xr, color, alpha);
                        
                    }
                    if(cx && (!bothBot))  // Don't draw the center line twice
                    {
                        // Draw top between lines
                        xl = sy < 0? (Sint16)max(-cx/sm + x, x - cy) : (Sint16)x - cy;
                        xr = ey < 0? (Sint16)min(-cx/em + x, x + cy) : (Sint16)x + cy;
                        if(xl <= xr && !(e180 && sy >= 0))
                            spg_linehblend(surf, xl, y - cx, xr, color, alpha);
                    }
                    else if(bothBot && reflex)
                    {
                        if(cx != 0)
                        {
                            // Draw entire top
                            spg_linehblend(surf, x - cy, y - cx, x + cy, color, alpha);
                        }
                        
                        // Draw separated bottom
                        // sy >= 0, ey > 0, sx < ex
                        xl = x - cy;  // Intercept of lines vs edge of circle
                        xr = sy > 0? (Sint16)min(cx/sm + x, x + cy) : x + cy;
                        if(xl <= xr && !s0 && !(sy > 0 && e0))
                            spg_linehblend(surf, xl, y + cx, xr, color, alpha);
                        
                        xl = ey > 0? (Sint16)max(cx/em + x, x - cy) : x - cy;
                        xr = x + cy;
                        if(xl <= xr && !(sy > 0 && e0))
                            spg_linehblend(surf, xl, y + cx, xr, color, alpha);
                        
                    }
                        
                }
                if(df < 0)
                {
                    df += d_e;
                    d_e += 2;
                    d_se += 2;
                }
                else
                {
                    df += d_se;
                    d_e += 2;
                    d_se += 4;
                    cy--;
                }
                cx++;
            }while(cx <= cy);
            */
        }


        virtual void Circle(Gui* gui, Sint16 x, Sint16 y, Sint16 radius, Uint32 color)
        {
            if(gui != NULL)
            {
                Sint16 dx = 0;
                Sint16 dy = (Sint16)(radius);
                Sint16 p = 1 - (Sint16)(radius);
                Sint16 d_e = 3;
                Sint16 d_se = -2 * (Sint16)(radius) + 5;
                
                do
                {
                    if(dx)
                    {
                        Pixel(gui, x + dx, y + dy, color);
                        Pixel(gui, x - dy, y - dx, color);
                        Pixel(gui, x - dx, y - dy, color);
                        Pixel(gui, x + dy, y - dx, color);
                    }
                    
                    Pixel(gui, x + dy, y + dx, color);
                    Pixel(gui, x - dx, y + dy, color);
                    Pixel(gui, x - dy, y + dx, color);
                    Pixel(gui, x + dx, y - dy, color);
                    
                    dx++;

                    if (p < 0)
                    {
                        p += d_e;
                        d_e += 2;
                        d_se += 2;
                    }
                    else
                    {
                        p += d_se;
                        d_e += 2;
                        d_se += 4;
                        dy--;
                    }
                }
                while (dx <= dy);
            }
        }

        virtual void CircleBlend(Gui* gui, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
                ;//SPG_CircleBlend(gui->screen, x, y, r, color, alpha);
        }

        virtual void CircleFilled(Gui* gui, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
        {
            if(gui != NULL)
            {
                Sint16 cx = 0;
                Sint16 cy = (Sint16)r;
                Sint16 df = 1 - cy;
                Sint16 d_e = 3;
                Sint16 d_se = -2*cy + 5;
                Sint16 xl, xr;
                
                do
                {
                    if(df >= 0)
                    {
                        // Draw bottom
                        xl = (Sint16)x - cx;
                        xr = (Sint16)x + cx;
                        LineH(gui, xl, y + cy, xr, color);//, alpha);
                        LineH(gui, xl, y - cy, xr, color);//, alpha);
                    }
                    if(cx != cy)
                    {
                        xl = (Sint16)x - cy;
                        xr = (Sint16)x + cy;
                        LineH(gui, xl, y + cx, xr, color);//, alpha);
                        if(cx)  // Don't draw the center line twice
                        {
                            // Draw top
                            xl = (Sint16)x - cy;
                            xr = (Sint16)x + cy;
                            LineH(gui, xl, y - cx, xr, color);//, alpha);
                        }
                    }
                    if(df < 0)
                    {
                        df += d_e;
                        d_e += 2;
                        d_se += 2;
                    }
                    else
                    {
                        df += d_se;
                        d_e += 2;
                        d_se += 4;
                        cy--;
                    }
                    cx++;
                }while(cx <= cy);
            }
        }

        virtual void CircleFilledBlend(Gui* gui, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
                ;//SPG_CircleFilledBlend(gui->screen, x, y, r, color, alpha);
        }

        virtual void EllipseFilled(Gui* gui, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
        {
            if(gui != NULL)
                ;//SPG_EllipseFilled(gui->screen, x, y, rx, ry, color);
        }

        virtual void EllipseFilledBlend(Gui* gui, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
        {
            if(gui != NULL)
                ;//SPG_EllipseFilledBlend(gui->screen, x, y, rx, ry, color, alpha);
        }

        virtual void TrigonFade(Gui* gui, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color1, Uint32 color2, Uint32 color3)
        {
            if(gui != NULL)
                ;//SPG_TrigonFade(gui->screen, x1, y1, x2, y2, x3, y3, color1, color2, color3);
        }



        virtual void ReadyDraw(Gui* gui)
        {
            if(gui != NULL && gui->screen != NULL)
            {
                currentClip.x = currentClip.y = 0;
                currentClip.w = gui->screen->w;
                currentClip.h = gui->screen->h;
            }
            glEnable(GL_SCISSOR_TEST);  // I should probably get the clip from this value instead?
        }
        
        virtual void DoneDraw(Gui* gui)
        {
            glDisable(GL_SCISSOR_TEST);
        }

        virtual SDL_Rect GetClip(Gui* gui)
        {
            return currentClip;
        }
        
        virtual void SetClip(Gui* gui, SDL_Rect& clip)
        {
            if(gui != NULL && gui->screen != NULL)
            {
                currentClip = clip;
                // Top
                GLdouble eqn0[4] = {0.0, 1.0, 0.0, -clip.y-1};
                glClipPlane (GL_CLIP_PLANE0, eqn0);
                glEnable (GL_CLIP_PLANE0);
                // Bottom
                GLdouble eqn1[4] = {0.0, -1.0, 0.0, clip.y + clip.h};
                glClipPlane (GL_CLIP_PLANE1, eqn1);
                glEnable (GL_CLIP_PLANE1);
                // Left
                GLdouble eqn2[4] = {1.0, 0.0, 0.0, -clip.x-1};
                glClipPlane (GL_CLIP_PLANE2, eqn2);
                glEnable (GL_CLIP_PLANE2);
                // Right
                GLdouble eqn3[4] = {1.0, 0.0, 0.0, clip.x + clip.w};
                glClipPlane (GL_CLIP_PLANE3, eqn3);
                glEnable (GL_CLIP_PLANE3);
                //int y = gui->screen->h - clip.y - clip.h;
                //int h = clip.h;
                //glScissor(0, y, clip.w, h);
            }
        }

        virtual void DirtyAdd(SDL_Rect* rect)
        {
            ;//if(SPG_DirtyEnabled())
                ;//SPG_DirtyAdd(rect);
        }
        

        virtual void RectIntersect(const SDL_Rect& A, const SDL_Rect& B, SDL_Rect& intersection)
        {
            int Amin, Amax, Bmin, Bmax;

            /* Horizontal intersection */
            Amin = A.x;
            Amax = Amin + A.w;
            Bmin = B.x;
            Bmax = Bmin + B.w;
            if(Bmin > Amin)
                    Amin = Bmin;
            intersection.x = Amin;
            if(Bmax < Amax)
                    Amax = Bmax;
            intersection.w = Amax - Amin > 0 ? Amax - Amin : 0;

            /* Vertical intersection */
            Amin = A.y;
            Amax = Amin + A.h;
            Bmin = B.y;
            Bmax = Bmin + B.h;
            if(Bmin > Amin)
                    Amin = Bmin;
            intersection.y = Amin;
            if(Bmax < Amax)
                    Amax = Bmax;
            intersection.h = Amax - Amin > 0 ? Amax - Amin : 0;
        }

        virtual void PushThickness(int thickness)
        {
            ;//SPG_PushThickness(thickness);
        }

        virtual int PopThickness()
        {
            return 0;//SPG_PopThickness();
        }
        
    };


}


#endif
